package com.doubao.user.security;

import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

/**
 * 用户上下文，用于获取当前登录用户信息
 */
@Slf4j
public class UserContext {

    private static final String USER_ID_HEADER = "X-User-ID";
    private static final String TOKEN_HEADER = "Authorization";
    
    // 为了向后兼容，保留ThreadLocal
    private static final ThreadLocal<Long> currentUserId = new ThreadLocal<>();
    // 新增 ThreadLocal 用于存储 Token
    private static final ThreadLocal<String> currentToken = new ThreadLocal<>();
    
    /**
     * 设置当前用户ID
     */
    public static void setUserId(Long userId) {
        log.debug("UserContext.setUserId: Setting userId {} in ThreadLocal.", userId);
        currentUserId.set(userId);
    }
    
    /**
     * 设置当前用户 Token
     */
    public static void setToken(String token) {
        log.debug("UserContext.setToken: Setting token in ThreadLocal.");
        // 存储原始的 Bearer Token 或仅存储 token 内容均可，这里存储去除 "Bearer " 前缀的 token
        if (token != null && token.startsWith("Bearer ")) {
            currentToken.set(token.substring(7));
        } else {
            currentToken.set(token);
        }
    }
    
    /**
     * 清除当前用户上下文
     */
    public static void clear() {
        log.debug("UserContext.clear: Clearing userId and token from ThreadLocal.");
        currentUserId.remove();
        currentToken.remove();
    }
    
    /**
     * 获取当前登录用户ID
     * 优先从 ThreadLocal 获取，如果没有则从请求头获取
     */
    public static Long getUserId() {
        // 优先从 ThreadLocal 获取
        Long userIdFromThreadLocal = currentUserId.get();
        if (userIdFromThreadLocal != null) {
            return userIdFromThreadLocal;
        }

        // 如果 ThreadLocal 中没有，则尝试从请求头获取
        HttpServletRequest request = getRequest();
        if (request != null) {
            String userIdStr = request.getHeader(USER_ID_HEADER);
            if (userIdStr != null && !userIdStr.isEmpty()) {
                try {
                    return Long.valueOf(userIdStr);
                } catch (NumberFormatException e) {
                    log.warn("UserContext.getUserId: Failed to parse X-User-ID header: {}", userIdStr);
                    return null;
                }
            }
        }

        log.warn("UserContext.getUserId: Could not get userId from ThreadLocal or Request Header.");
        return null;
    }
    
    /**
     * 获取当前登录用户Token (去除 "Bearer " 前缀)
     * 优先从 ThreadLocal 获取，如果没有则从请求头获取
     */
    public static String getToken() {
        // 优先从 ThreadLocal 获取
        String tokenFromThreadLocal = currentToken.get();
        if (tokenFromThreadLocal != null) {
            return tokenFromThreadLocal;
        }

        // 如果 ThreadLocal 中没有，则尝试从请求头获取
        HttpServletRequest request = getRequest();
        if (request == null) {
            log.warn("UserContext.getToken: HttpServletRequest is null, cannot get token from header.");
            return null;
        }

        String token = request.getHeader(TOKEN_HEADER);
        if (token != null && token.startsWith("Bearer ")) {
            return token.substring(7);
        }

        // 如果请求头中没有 Bearer token，可能直接是 token
        if (token != null) {
             log.warn("UserContext.getToken: Token found in header but might not be Bearer type.");
             return token; // 返回原始 token 或 null 取决于业务需要
        }

        log.warn("UserContext.getToken: Could not get token from ThreadLocal or Request Header.");
        return null;
    }
    
    /**
     * 判断用户是否已登录
     */
    public static boolean isUserLoggedIn() {
        // 判断登录状态可以基于 userId 或 token，这里基于 userId
        return getUserId() != null;
    }
    
    /**
     * 获取当前请求
     */
    private static HttpServletRequest getRequest() {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (attributes == null) {
            // 这个警告很重要，表明上下文可能丢失
            log.warn("UserContext.getRequest: RequestAttributes are null. Cannot get HttpServletRequest. This might happen in async/feign calls if context is not propagated.");
            return null;
        }
        
        return attributes.getRequest();
    }
}